package com.unitlib.base.utils;

import com.unitlib.base.utils.Base64Utils;

import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

@SuppressWarnings("all")
public class CipherUtil {

    private static final String TAG = "CipherUtil";

    //加密
    public final static byte[] KEY = "35G3QASfE0asBFhD".getBytes();
    public final static byte[] IV = "1qwe8Gkl99ik4Bq6".getBytes();

    /**
     * 加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryption(byte[] data, byte[] KEY, byte[] IV) throws Exception {
        return cipherIV(Cipher.ENCRYPT_MODE, data, KEY, IV);
    }

    /**
     * 解密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] decryption(byte[] data, byte[] KEY, byte[] IV) throws Exception {
        return cipherIV(Cipher.DECRYPT_MODE, data, KEY, IV);
    }

    private static byte[] cipherIV(int mode, byte[] data, byte[] KEY, byte[] IV) throws Exception {
        SecretKeySpec sekey = new SecretKeySpec(KEY, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(mode, sekey, new IvParameterSpec(IV));
        byte[] decrypted = cipher.doFinal(data);
        return decrypted;
    }

    /**
     * 2进制转16进制
     *
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**
     * 16进制转2进制
     *
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length() / 2];
        for (int i = 0; i < hexStr.length() / 2; i++) {
            int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static byte[] encryption(byte[] data) {
        try {
            return cipherIV(Cipher.ENCRYPT_MODE, data);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] decryption(byte[] data) throws Exception {
        return cipherIV(Cipher.DECRYPT_MODE, data);
    }

    private static byte[] cipherIV(int mode, byte[] data) throws Exception {
        SecretKeySpec sekey = new SecretKeySpec(KEY, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(mode, sekey, new IvParameterSpec(IV));
        byte[] decrypted = cipher.doFinal(data);
        return decrypted;
    }

    private static byte[] cipher(int mode, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(mode, new SecretKeySpec(KEY, "AES"));
        byte[] decrypted = cipher.doFinal(data);
        return decrypted;
    }

    public static String decryption(String str, byte[] KEY, byte[] IV) {
        try {
            return new String(decryption(parseHexStr2Byte(str), KEY, IV), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return str;
        }
    }

    public static String encryption(String str, byte[] KEY, byte[] IV) {
        try {
            return parseByte2HexStr(encryption(str.getBytes("utf-8"), KEY, IV));
        } catch (Exception e) {
            e.printStackTrace();
            return str;
        }
    }

    public static void main(String[] args) throws Exception {
        System.out.println("KEY:6QGnQV9Lg0aeBFTD");
        System.out.println("IV:c2GhJeEdzZgLRjMm");
        String str = "zhangsan1";
        System.out.println("加密前:" + str);
        String str1 = new String(Base64Utils.encode(encryption(str.getBytes())));// 加密后
        System.out.println("加密后:" + str1);
        String str2 = new String(decryption(Base64Utils.decode(str1)));// 解密后
        System.out.println("解密后:" + str2);

        str1 = "LIuAX0sBLCi45Y9QITMKxMuZrlDm4yGXipHBJzmDLNw=";

        String k = "CkPb5vQwUiGmUgYf";
        String i = "2730783402156240";
        str2 = new String(decryption(Base64Utils.decode(str1), k.getBytes(), i.getBytes()));// 解密后
        System.out.println(str2);
//        随机生成KEY
//        for (int i = 1; i < 21; i++) {
//            System.out.print("AESKeymap.put(\""+i+"\", \"");
//            getKey();
//            System.out.print("\");");
//            System.out.println("");
//        }
        get16Key();

        //密匙 生成地址 https://suijimimashengcheng.51240.com/
    }

    public static void get16IV() {

    }

    /**
     * 随机生成16位秘钥
     */
    public static void get16Key() {
        try {
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            kg.init(256);// 要生成多少位，只需要修改这里即可128, 192或256
            SecretKey sk = kg.generateKey();
            byte[] b = sk.getEncoded();
            String s = byteToHexString(b);
            System.out.println(s.substring(0, 16));
            //System.out.println("十六进制密钥长度为" + s.length());
            //System.out.println("二进制密钥的长度为" + s.length() * 4);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            System.out.println("没有此算法。");
        }
    }


    /**
     * byte数组转化为16进制字符串
     *
     * @param bytes
     * @return
     */
    public static String byteToHexString(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < bytes.length; i++) {
            String strHex = Integer.toHexString(bytes[i]);
            if (strHex.length() > 3) {
                sb.append(strHex.substring(6));
            } else {
                if (strHex.length() < 2) {
                    sb.append("0" + strHex);
                } else {
                    sb.append(strHex);
                }
            }
        }
        return sb.toString();
    }


}